#ifndef _DESC_H_
#define _DESC_H_
/*
	Copyright (C) 2010 Salil Bhagurkar

	This file is part of salil64

	salil64 is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	salil64 is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with salil64.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "types.h"


#define KERNEL_CS 0x08


struct IdtEntry {
	u16 offset_low;
	u16 segment;
	unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
	u16 offset_middle;
	u32 offset_high;
	u32 zero1;
} __attribute__((packed));

enum {
	GATE_INTERRUPT = 0xE,
	GATE_TRAP = 0xF,
	GATE_CALL = 0xC,
	GATE_TASK = 0x5,
};

#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)


static inline void packIdtEntry(struct IdtEntry *idtEntry, unsigned type, unsigned long func,
			     unsigned dpl, unsigned ist)
{
	idtEntry->offset_low = PTR_LOW(func);
	idtEntry->segment = KERNEL_CS;
	idtEntry->ist = ist;
	idtEntry->p = 1;
	idtEntry->dpl = dpl;
	idtEntry->zero0 = 0;
	idtEntry->zero1 = 0;
	idtEntry->type = type;
	idtEntry->offset_middle = PTR_MIDDLE(func);
	idtEntry->offset_high = PTR_HIGH(func);
}


struct DescPtr {
	unsigned short size;
	unsigned long address;
} __attribute__((packed)) ;

static inline void loadIdt(const struct DescPtr *dtr)
{
	asm volatile("lidt %0"::"m" (*dtr));
}

static inline void storeIdt(struct DescPtr *dtr)
{
	asm volatile("sidt %0":"=m" (*dtr));
}


#endif /*_DESC_H_*/
